package main

import (
	"fmt"
	"time"
)

func recv(c <-chan int) {
	ret := <-c
	fmt.Println("接收成功", ret)
}

// 没有缓冲区通道
func noBufferChannel() {
	ch := make(chan int)
	go recv(ch) // 启用goroutine从通道接收值
	ch <- 10
	fmt.Println("发送成功")
}
func noBufferChannelBlocked() {
	ch := make(chan int)
	ch <- 10
	fmt.Println("发送成功")
	//fatal error: all goroutines are asleep - deadlock!
}

// 有缓存区通道
func withBufferChannel() {
	ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
	ch <- 10
	fmt.Println("发送成功1")
	go recv(ch)
	fmt.Println("发送成功2")
	ch <- 10 // 阻塞
	go recv(ch)
}

// 循环读取通道
func loopReadChannel() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	// 开启goroutine将0~100的数发送到ch1中
	go func() {
		for i := 0; i < 100; i++ {
			ch1 <- i
		}
		close(ch1) // 关闭之后，不可以再写，但是可以读
		fmt.Println("CLose CH1")
	}()
	// 开启goroutine从ch1中接收值，并将该值的平方发送到ch2中
	go func() {
		time.Sleep(10 * time.Millisecond)
		for {
			i, ok := <-ch1 // 通道关闭后再取值ok=false
			if !ok {
				break
			}
			ch2 <- i * i
		}
		close(ch2)
		fmt.Println("CLose CH2")
	}()

	// 在主goroutine中从ch2中接收值打印
	for i := range ch2 { // 通道关闭后会退出for range循环
		fmt.Println(i)
	}
}

// 单向通道，多用在函数的参数
func counter(out chan<- int) {
	for i := 0; i < 100; i++ {
		out <- i
	}
	close(out)
}

// chan<- int是一个只写单向通道（只能对其写入int类型值），可以对其执行发送操作但是不能执行接收操作；
// <-chan int是一个只读单向通道（只能从其读取int类型值），可以对其执行接收操作但是不能执行发送操作。
func squarer(out chan<- int, in <-chan int) {
	for i := range in {
		out <- i * i
	}
	close(out)
}
func printer(in <-chan int) {
	for i := range in {
		fmt.Println(i)
	}
}

func main() {
	//noBufferChannel()
	//noBufferChannelBlocked()
	//withBufferChannel()
	loopReadChannel()
	time.Sleep(20 * time.Millisecond)
}
